package com.fary.web.servlet.config.annotation;

import com.fary.util.PathMatcher;
import com.fary.web.util.UrlPathHelper;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Predicate;

public class PathMatchConfigurer {

	private Boolean suffixPatternMatch;

	private Boolean trailingSlashMatch;

	private Boolean registeredSuffixPatternMatch;

	private UrlPathHelper urlPathHelper;

	private PathMatcher pathMatcher;

	private Map<String, Predicate<Class<?>>> pathPrefixes;


	/**
	 * setUseSuffixPatternMatch默认设置为true,
	 * 那么/user 就会匹配 /user.*,也就是说,/user.html 的请求会被 /user 的 Controller所拦截.
	 */
	public PathMatchConfigurer setUseSuffixPatternMatch(Boolean suffixPatternMatch) {
		this.suffixPatternMatch = suffixPatternMatch;
		return this;
	}

	/**
	 * setUseTrailingSlashMatch的默认值为true
	 * 也就是说, "/user" 和 "/user/" 都会匹配到 "/user"的Controller
	 */
	public PathMatchConfigurer setUseTrailingSlashMatch(Boolean trailingSlashMatch) {
		this.trailingSlashMatch = trailingSlashMatch;
		return this;
	}

	/**
	 * 配置后置模式匹配是否仅在配置内容协商中明确指定的路径扩展名称时生效
	 * 举个例子：假设WebMvcConfigurer中覆盖了configureContentNegotiation方法进行以下处理：
	 *
	 * public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
	 *     configurer.mediaType("pdf", MediaType.APPLICATION_PDF);
	 *}
	 * 当setUseRegisteredSuffixPatternMatch配置成TRUE时，即使setUseSuffixPatternMatch设置成True，
	 * 在访问/test.do时也不会命中被RequestMapping注解值为/test的Controller；
	 * 只有在访问/test.pdf时才能正常访问，其它任何的/test.txt或者/test.doc等均会报404；
	 * 默认情况下该值是False
	 */
	public PathMatchConfigurer setUseRegisteredSuffixPatternMatch(Boolean registeredSuffixPatternMatch) {
		this.registeredSuffixPatternMatch = registeredSuffixPatternMatch;
		return this;
	}

	/**
	 * 设置 UrlPathHelper 以用于解析查找路径。
	 * 使用它来使用自定义子类覆盖默认 UrlPathHelper，或在多个 HandlerMappings 和 MethodNameResolver 之间共享通用 UrlPathHelper 设置。
	 */
	public PathMatchConfigurer setUrlPathHelper(UrlPathHelper urlPathHelper) {
		this.urlPathHelper = urlPathHelper;
		return this;
	}

	/**
	 * 设置 PathMatcher 实现以用于将 URL 路径与注册的 URL 模式匹配。默认为 AntPathMatcher。
	 */
	public PathMatchConfigurer setPathMatcher(PathMatcher pathMatcher) {
		this.pathMatcher = pathMatcher;
		return this;
	}

	/**
	 * 接口请求添加统一的前缀
	 * configurer.addPathPrefix("/api", c -> c.isAnnotationPresent(Controller.class))
	 * 			 .addPathPrefix("/api", c -> c.isAnnotationPresent(RestController.class));
	 */
	public PathMatchConfigurer addPathPrefix(String prefix, Predicate<Class<?>> predicate) {
		if (this.pathPrefixes == null) {
			this.pathPrefixes = new LinkedHashMap<>();
		}
		this.pathPrefixes.put(prefix, predicate);
		return this;
	}


	public Boolean isUseSuffixPatternMatch() {
		return this.suffixPatternMatch;
	}

	public Boolean isUseTrailingSlashMatch() {
		return this.trailingSlashMatch;
	}

	public Boolean isUseRegisteredSuffixPatternMatch() {
		return this.registeredSuffixPatternMatch;
	}

	public UrlPathHelper getUrlPathHelper() {
		return this.urlPathHelper;
	}

	public PathMatcher getPathMatcher() {
		return this.pathMatcher;
	}

	protected Map<String, Predicate<Class<?>>> getPathPrefixes() {
		return this.pathPrefixes;
	}
}